'use strict';
angular.module('hanxinBroker').directive('fieldError', function fieldError() {
  return {
    restrict: 'A',
    require: ['ngModel', '^?form'],
    link: function (scope, element, attrs, requires) {
      var ngModel = requires[0];
      var form = requires[1];
      var options = scope.$eval(attrs.fieldError);
      var tips = attrs.fieldTip;
      var minLength = scope.$eval(attrs.ngMinlength);
      var maxLength = scope.$eval(attrs.ngMaxlength);
      var min = +attrs.min;
      var max = +attrs.max;
      var step = +attrs.step;
      options = _.defaults({}, options, {
        required: '此项为必填项',
        minlength: '长度不能小于' + minLength + '个字符',
        maxlength: '长度不能大于' + maxLength + '个字符',
        // TODO: 实现这一系列验证器
        remote: '远程校验错误',
        word: '需是字母+数字的组合',
        username: '只能使用数字字母下划线，且需以字母或下划线开头',
        personalId: '不是有效的身份证号',
        pattern: '数据格式不正确',
        email: '需是有效的邮件地址',
        password: '不能使用纯数字',
        url: '需是有效的网址',
        number: '需是有效的数字',
        bankcard: '需是有效的银行卡号',
        mobile: '需是有效的手机号',
        phone: '需是有效的座机号',
        unique: '此项需唯一，但系统中有相同数据',
        same: '此项需与上一项完全相同',
        diff: '此项需与上一项不同',
        step: '需按递增值递增: ' + step,
        min: '不能小于最小值: ' + min,
        max: '不能大于最大值: ' + max
      });
      var subScope = scope.$new();
      var vm = subScope.vm = {};
      vm.visible = function () {
        // 没有提示或没有焦点时才显示错误信息
        return (!tips || !ngModel.$focused) && ngModel.$invalid && (!ngModel.$pristine || (form && form.$submitted));
      };
      vm.errors = function () {
        var result = [];
        _.each(ngModel.$error, function (value, key) {
          if (value) {
            if (key === 'remote') {
              if (ngModel.$remoteError) {
                result.push(ngModel.$remoteError);
              }
            } else {
              var msg = options[key];
              if (msg) {
                result.push(options[key]);
              } else {
                console.error('未知的键值：', key);
              }
            }
          }
        });
        return result;
      };
      element.bind('focus', function () {
        subScope.$apply(function () {
          ngModel.$focused = true;
        });
      });
      element.bind('blur', function () {
        subScope.$apply(function () {
          ngModel.$focused = false;
        });
      });

      var $wrapper = element.parent();
      if (!$wrapper.hasClass('input-wrapper')) {
        $wrapper = element.wrap('<div class="input-wrapper"></div>').parent();
      }
      var $errors = angular.element('<div class="floating label label-danger" style="display:block"></div>');
      $errors.insertAfter(element);
      subScope.$watch(function () {
        return vm.visible();
      }, function (visible) {
        if (visible && !_.isEmpty(vm.errors())) {
          $errors.show();
        }
        else {
          $errors.hide();
        }
      });
      // 为了解决ie8下的奇葩问题，改用这种方式来更新错误信息
      subScope.$watch(function () {
        return vm.errors().join(',');
      }, function () {
        var errors = '';
        _.each(vm.errors(), function (error) {
          errors += '<div>' + error + '</div>';
        });
        $errors.html(errors);
      });
    }
  };
});
